package net.iponweb.disthene.reader.handler.parameters; import io.netty.handler.codec.http.HttpContent; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.QueryStringDecoder; import net.iponweb.disthene.reader.exceptions.InvalidParameterValueException; import net.iponweb.disthene.reader.exceptions.ParameterParsingException; import net.iponweb.disthene.reader.format.Format; import net.iponweb.disthene.reader.graph.ColorTable; import net.iponweb.disthene.reader.graph.Graph; import net.iponweb.disthene.reader.graphite.utils.UnitSystem; import org.apache.log4j.Logger; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import java.awt.*; import java.lang.String; import java.lang.Integer; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author Andrei Ivanov */ public class RenderParameters { final static Logger logger = Logger.getLogger(RenderParameters.class); final private static Pattern EXTENDED_TIME_PATTERN = Pattern.compile("-*([0-9]+)([a-zA-Z]+)"); private String tenant; private List<String> targets = new ArrayList<>(); private Long from; private Long until; private Format format; private DateTimeZone tz; private int maxDataPoints = Integer.MAX_VALUE; private ImageParameters imageParameters = new ImageParameters(); public String getTenant() { return tenant; } public void setTenant(String tenant) { this.tenant = tenant; } public List<String> getTargets() { return targets; } public Long getFrom() { return from; } public void setFrom(Long from) { this.from = from; } public Long getUntil() { return until; } public void setUntil(Long until) { this.until = until; } public Format getFormat() { return format; } public void setFormat(Format format) { this.format = format; } public DateTimeZone getTz() { return tz; } public void setTz(DateTimeZone tz) { this.tz = tz; } public int getMaxDataPoints() { return maxDataPoints; } public void setMaxDataPoints(int maxDataPoints) { this.maxDataPoints = maxDataPoints; } public void setImageParameters(ImageParameters imageParameters) { this.imageParameters = imageParameters; } public ImageParameters getImageParameters() { return imageParameters; } @Override public String toString() { return "RenderParameters{" + "tenant='" + tenant + '\'' + ", targets=" + targets + ", from=" + from + ", until=" + until + ", format=" + format + ", tz=" + tz + ", imageParameters=" + imageParameters + '}'; } public static RenderParameters parse(HttpRequest request) throws ParameterParsingException { //todo: do it in some beautiful way String parameterString; if (request.getMethod().equals(HttpMethod.POST)) { ((HttpContent) request).content().resetReaderIndex(); byte[] bytes = new byte[((HttpContent) request).content().readableBytes()]; ((HttpContent) request).content().readBytes(bytes); parameterString = "/render/?" + new String(bytes); } else { parameterString = request.getUri(); } logger.debug(parameterString); QueryStringDecoder queryStringDecoder = new QueryStringDecoder(parameterString); RenderParameters parameters = new RenderParameters(); if (queryStringDecoder.parameters().get("tenant") != null) { parameters.setTenant(queryStringDecoder.parameters().get("tenant").get(0)); } else { // assume tenant "NONE" parameters.setTenant("NONE"); logger.debug("No tenant in request. Assuming NONE"); } if (queryStringDecoder.parameters().get("target") != null) { for (String path : queryStringDecoder.parameters().get("target")) { parameters.getTargets().add(path); } } // First decode tz and default to UTC if (queryStringDecoder.parameters().get("tz") != null) { try { parameters.setTz(DateTimeZone.forID(queryStringDecoder.parameters().get("tz").get(0))); } catch (Exception e) { throw new InvalidParameterValueException("Timezone not found: " + queryStringDecoder.parameters().get("tz").get(0)); } } else { parameters.setTz(DateTimeZone.UTC); } // parse from defaulting to -1d if (queryStringDecoder.parameters().get("from") != null) { try { parameters.setFrom(parseExtendedTime(queryStringDecoder.parameters().get("from").get(0), parameters.getTz())); } catch (NumberFormatException e) { throw new InvalidParameterValueException("DateTime format not recognized (from): " + queryStringDecoder.parameters().get("from").get(0)); } } else { // default to -1d parameters.setFrom((System.currentTimeMillis() / 1000L) - 86400); } // parse until if ((queryStringDecoder.parameters().get("until") != null) || (queryStringDecoder.parameters().get("until").get(0).equals("now"))) { try { parameters.setUntil(parseExtendedTime(queryStringDecoder.parameters().get("until").get(0), parameters.getTz())); } catch (NumberFormatException e) { throw new InvalidParameterValueException("DateTime format not recognized (until): " + queryStringDecoder.parameters().get("until").get(0)); } } else { // default to now parameters.setUntil(System.currentTimeMillis() / 1000L); } // Prohibiting "from greater than until" if (parameters.getFrom() > parameters.getUntil()) { parameters.setFrom(parameters.getUntil()); } // Prohibiting "until in the future" if (parameters.getUntil() > (System.currentTimeMillis() / 1000L)) { parameters.setUntil(System.currentTimeMillis() / 1000L); } // parse format defaulting to PNG if (queryStringDecoder.parameters().get("format") != null) { try { parameters.setFormat(Format.valueOf(queryStringDecoder.parameters().get("format").get(0).toUpperCase())); } catch (IllegalArgumentException e) { throw new InvalidParameterValueException("Format not supported: " + queryStringDecoder.parameters().get("format").get(0)); } } else { // default to now parameters.setFormat(Format.PNG); } if (queryStringDecoder.parameters().get("maxDataPoints") != null) { try { parameters.setMaxDataPoints(Integer.valueOf(queryStringDecoder.parameters().get("maxDataPoints").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("fontSize format : " + queryStringDecoder.parameters().get("fontSize").get(0)); } } //************************************************************************************************************* // Image parameters //************************************************************************************************************* if (queryStringDecoder.parameters().get("areaAlpha") != null) { try { Float areaAlpha = Float.valueOf(queryStringDecoder.parameters().get("areaAlpha").get(0)); if (areaAlpha < 0.) areaAlpha = 0f; if (areaAlpha > 1.) areaAlpha = 1f; parameters.getImageParameters().setAreaAlpha(areaAlpha); } catch (NumberFormatException e) { throw new InvalidParameterValueException("AreaAlpha format : " + queryStringDecoder.parameters().get("areaAlpha").get(0)); } } if (queryStringDecoder.parameters().get("areaMode") != null) { try { parameters.getImageParameters().setAreaMode(ImageParameters.AreaMode.valueOf(queryStringDecoder.parameters().get("areaMode").get(0).toUpperCase())); } catch (IllegalArgumentException e) { throw new InvalidParameterValueException("Unknown area mode : " + queryStringDecoder.parameters().get("areaMode").get(0).toUpperCase()); } } if (queryStringDecoder.parameters().get("bgcolor") != null) { Color color = ColorTable.getColorByName(queryStringDecoder.parameters().get("bgcolor").get(0).replaceAll("^\"|\"$", "")); if (color != null) parameters.getImageParameters().setBackgroundColor(color); } if (queryStringDecoder.parameters().get("colorList") != null) { String colorsString = queryStringDecoder.parameters().get("colorList").get(0).replaceAll("^\"|\"$", ""); String[] split = colorsString.split(","); List<Color> colors = new ArrayList<>(); for (String c : split) { Color color = ColorTable.getColorByName(c); if (color != null) colors.add(color); } if (colors.size() > 0) { parameters.getImageParameters().setColorList(colors); } } if (queryStringDecoder.parameters().get("drawNullAsZero") != null) { parameters.getImageParameters().setDrawNullAsZero(Boolean.parseBoolean(queryStringDecoder.parameters().get("drawNullAsZero").get(0))); } if (queryStringDecoder.parameters().get("fgcolor") != null) { Color color = ColorTable.getColorByName(queryStringDecoder.parameters().get("fgcolor").get(0).replaceAll("^\"|\"$", "")); if (color != null) parameters.getImageParameters().setForegroundColor(color); } if (queryStringDecoder.parameters().get("fontBold") != null) { parameters.getImageParameters().setFontBold(Boolean.parseBoolean(queryStringDecoder.parameters().get("fontBold").get(0))); } if (queryStringDecoder.parameters().get("fontItalic") != null) { parameters.getImageParameters().setFontItalic(Boolean.parseBoolean(queryStringDecoder.parameters().get("fontItalic").get(0))); } if (queryStringDecoder.parameters().get("fontName") != null) { parameters.getImageParameters().setFontName(queryStringDecoder.parameters().get("fontName").get(0).toLowerCase()); } if (queryStringDecoder.parameters().get("fontSize") != null) { try { parameters.getImageParameters().setFontSize(Float.valueOf(queryStringDecoder.parameters().get("fontSize").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("fontSize format : " + queryStringDecoder.parameters().get("fontSize").get(0)); } } if (queryStringDecoder.parameters().get("graphOnly") != null) { parameters.getImageParameters().setGraphOnly(Boolean.parseBoolean(queryStringDecoder.parameters().get("graphOnly").get(0))); } if (queryStringDecoder.parameters().get("graphType") != null) { try { parameters.getImageParameters().setGraphType(Graph.GraphType.valueOf(queryStringDecoder.parameters().get("graphType").get(0).toUpperCase())); } catch (IllegalArgumentException e) { throw new InvalidParameterValueException("Unknown graphType : " + queryStringDecoder.parameters().get("graphType").get(0).toUpperCase()); } } if (queryStringDecoder.parameters().get("hideLegend") != null) { boolean hideLegend = Boolean.parseBoolean(queryStringDecoder.parameters().get("hideLegend").get(0)); if (hideLegend) { parameters.getImageParameters().setHideLegendCompletely(true); } else { parameters.getImageParameters().setHideLegend(false); } } if (queryStringDecoder.parameters().get("hideAxes") != null) { parameters.getImageParameters().setHideAxes(Boolean.parseBoolean(queryStringDecoder.parameters().get("hideAxes").get(0))); } if (queryStringDecoder.parameters().get("hideYAxes") != null) { parameters.getImageParameters().setHideYAxis(Boolean.parseBoolean(queryStringDecoder.parameters().get("hideYAxes").get(0))); } if (queryStringDecoder.parameters().get("hideGrid") != null) { parameters.getImageParameters().setHideGrid(Boolean.parseBoolean(queryStringDecoder.parameters().get("hideGrid").get(0))); } if (queryStringDecoder.parameters().get("height") != null) { try { parameters.getImageParameters().setHeight(Integer.valueOf(queryStringDecoder.parameters().get("height").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("Height format : " + queryStringDecoder.parameters().get("height").get(0)); } } if (queryStringDecoder.parameters().get("leftColor") != null) { Color color = ColorTable.getColorByName(queryStringDecoder.parameters().get("leftColor").get(0).replaceAll("^\"|\"$", "")); if (color != null) parameters.getImageParameters().setLeftColor(color); } if (queryStringDecoder.parameters().get("leftDashed") != null) { parameters.getImageParameters().setLeftDashed(Boolean.parseBoolean(queryStringDecoder.parameters().get("leftDashed").get(0))); } if (queryStringDecoder.parameters().get("leftWidth") != null) { try { parameters.getImageParameters().setLeftWidth(Double.valueOf(queryStringDecoder.parameters().get("leftWidth").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("leftWidth format : " + queryStringDecoder.parameters().get("leftWidth").get(0)); } } if (queryStringDecoder.parameters().get("lineMode") != null) { try { parameters.getImageParameters().setLineMode(ImageParameters.LineMode.valueOf(queryStringDecoder.parameters().get("lineMode").get(0).toUpperCase())); } catch (IllegalArgumentException e) { throw new InvalidParameterValueException("Unknown line mode : " + queryStringDecoder.parameters().get("lineMode").get(0).toUpperCase()); } } if (queryStringDecoder.parameters().get("lineWidth") != null) { try { parameters.getImageParameters().setLineWidth(Double.valueOf(queryStringDecoder.parameters().get("lineWidth").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("lineWidth format : " + queryStringDecoder.parameters().get("lineWidth").get(0)); } } if (queryStringDecoder.parameters().get("logBase") != null) { try { Double logBase = Double.valueOf(queryStringDecoder.parameters().get("logBase").get(0)); if (logBase > 0 && logBase != 1) { parameters.getImageParameters().setLogBase(logBase); } } catch (NumberFormatException e) { throw new InvalidParameterValueException("lineWidth format : " + queryStringDecoder.parameters().get("lineWidth").get(0)); } } if (queryStringDecoder.parameters().get("majorGridLineColor") != null) { Color color = ColorTable.getColorByName(queryStringDecoder.parameters().get("majorGridLineColor").get(0).replaceAll("^\"|\"$", "")); if (color != null) parameters.getImageParameters().setMajorGridLineColor(color); } if (queryStringDecoder.parameters().get("margin") != null) { try { Double margin = Double.valueOf(queryStringDecoder.parameters().get("margin").get(0)); if (margin > 0) { parameters.getImageParameters().setMargin(margin.intValue()); } } catch (NumberFormatException e) { throw new InvalidParameterValueException("margin format : " + queryStringDecoder.parameters().get("margin").get(0)); } } if (queryStringDecoder.parameters().get("minorGridLineColor") != null) { Color color = ColorTable.getColorByName(queryStringDecoder.parameters().get("minorGridLineColor").get(0).replaceAll("^\"|\"$", "")); if (color != null) parameters.getImageParameters().setMinorGridLineColor(color); } if (queryStringDecoder.parameters().get("minorY") != null) { try { Double minorY = Double.valueOf(queryStringDecoder.parameters().get("minorY").get(0)); if (minorY >= 0) { parameters.getImageParameters().setMinorY(minorY.intValue()); } } catch (NumberFormatException e) { throw new InvalidParameterValueException("minorY format : " + queryStringDecoder.parameters().get("minorY").get(0)); } } if (queryStringDecoder.parameters().get("minXStep") != null) { try { Double minXStep = Double.valueOf(queryStringDecoder.parameters().get("minXStep").get(0)); if (minXStep >= 0) { parameters.getImageParameters().setMinXStep(minXStep.intValue()); } } catch (NumberFormatException e) { throw new InvalidParameterValueException("minXStep format : " + queryStringDecoder.parameters().get("minXStep").get(0)); } } if (queryStringDecoder.parameters().get("pieMode") != null) { try { parameters.getImageParameters().setPieMode(Graph.PieMode.valueOf(queryStringDecoder.parameters().get("pieMode").get(0).toUpperCase())); } catch (IllegalArgumentException e) { throw new InvalidParameterValueException("Unknown pieMode : " + queryStringDecoder.parameters().get("pieMode").get(0).toUpperCase()); } } if (queryStringDecoder.parameters().get("pieLabels") != null) { try { parameters.getImageParameters().setPieLabelsOrientation(Graph.PieLabelsOrientation.valueOf(queryStringDecoder.parameters().get("pieLabels").get(0).toUpperCase())); } catch (IllegalArgumentException e) { throw new InvalidParameterValueException("Unknown pieLabels : " + queryStringDecoder.parameters().get("pieLabels").get(0).toUpperCase()); } } if (queryStringDecoder.parameters().get("rightColor") != null) { Color color = ColorTable.getColorByName(queryStringDecoder.parameters().get("rightColor").get(0).replaceAll("^\"|\"$", "")); if (color != null) parameters.getImageParameters().setRightColor(color); } if (queryStringDecoder.parameters().get("rightDashed") != null) { parameters.getImageParameters().setRightDashed(Boolean.parseBoolean(queryStringDecoder.parameters().get("rightDashed").get(0))); } if (queryStringDecoder.parameters().get("rightWidth") != null) { try { parameters.getImageParameters().setRightWidth(Double.valueOf(queryStringDecoder.parameters().get("rightWidth").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("rightWidth format : " + queryStringDecoder.parameters().get("rightWidth").get(0)); } } if (queryStringDecoder.parameters().get("title") != null) { parameters.getImageParameters().setTitle(queryStringDecoder.parameters().get("title").get(0).replaceAll("^\"|\"$", "")); } if (queryStringDecoder.parameters().get("uniqueLegend") != null) { parameters.getImageParameters().setUniqueLegend(Boolean.parseBoolean(queryStringDecoder.parameters().get("uniqueLegend").get(0))); } if (queryStringDecoder.parameters().get("valueLabels") != null) { try { parameters.getImageParameters().setPieLabelsStyle(Graph.PieLabelsStyle.valueOf(queryStringDecoder.parameters().get("valueLabels").get(0).toUpperCase())); } catch (IllegalArgumentException e) { throw new InvalidParameterValueException("Unknown valueLabels : " + queryStringDecoder.parameters().get("valueLabels").get(0).toUpperCase()); } } if (queryStringDecoder.parameters().get("valueLabelsMin") != null) { try { parameters.getImageParameters().setPieLabelsMin(Double.valueOf(queryStringDecoder.parameters().get("valueLabelsMin").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("valueLabelsMin format : " + queryStringDecoder.parameters().get("valueLabelsMin").get(0)); } } if (queryStringDecoder.parameters().get("vtitle") != null) { parameters.getImageParameters().setVerticalTitle(queryStringDecoder.parameters().get("vtitle").get(0).replaceAll("^\"|\"$", "")); } if (queryStringDecoder.parameters().get("vtitleRight") != null) { parameters.getImageParameters().setVerticalTitleRight(queryStringDecoder.parameters().get("vtitleRight").get(0).replaceAll("^\"|\"$", "")); } if (queryStringDecoder.parameters().get("width") != null) { try { parameters.getImageParameters().setWidth(Integer.valueOf(queryStringDecoder.parameters().get("width").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("Width format : " + queryStringDecoder.parameters().get("width").get(0)); } } if (queryStringDecoder.parameters().get("yAxisSide") != null) { try { parameters.getImageParameters().setyAxisSide(ImageParameters.Side.valueOf(queryStringDecoder.parameters().get("yAxisSide").get(0).toUpperCase())); } catch (IllegalArgumentException e) { throw new InvalidParameterValueException("Unknown y axis side : " + queryStringDecoder.parameters().get("yAxisSide").get(0).toUpperCase()); } } if (queryStringDecoder.parameters().get("yMax") != null) { try { parameters.getImageParameters().setyMax(Double.valueOf(queryStringDecoder.parameters().get("yMax").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("yMax format : " + queryStringDecoder.parameters().get("yMax").get(0)); } } if (queryStringDecoder.parameters().get("yMaxLeft") != null) { try { parameters.getImageParameters().setyMaxLeft(Double.valueOf(queryStringDecoder.parameters().get("yMaxLeft").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("yMaxLeft format : " + queryStringDecoder.parameters().get("yMaxLeft").get(0)); } } if (queryStringDecoder.parameters().get("yMaxRight") != null) { try { parameters.getImageParameters().setyMaxRight(Double.valueOf(queryStringDecoder.parameters().get("yMaxRight").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("yMaxRight format : " + queryStringDecoder.parameters().get("yMaxRight").get(0)); } } if (queryStringDecoder.parameters().get("yMin") != null) { try { parameters.getImageParameters().setyMin(Double.valueOf(queryStringDecoder.parameters().get("yMin").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("yMin format : " + queryStringDecoder.parameters().get("yMin").get(0)); } } if (queryStringDecoder.parameters().get("yMinLeft") != null) { try { parameters.getImageParameters().setyMinLeft(Double.valueOf(queryStringDecoder.parameters().get("yMinLeft").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("yMinLeft format : " + queryStringDecoder.parameters().get("yMinLeft").get(0)); } } if (queryStringDecoder.parameters().get("yMinRight") != null) { try { parameters.getImageParameters().setyMinRight(Double.valueOf(queryStringDecoder.parameters().get("yMinRight").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("yMinRight format : " + queryStringDecoder.parameters().get("yMinRight").get(0)); } } if (queryStringDecoder.parameters().get("yStep") != null) { try { parameters.getImageParameters().setyStep(Double.valueOf(queryStringDecoder.parameters().get("yStep").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("yStep format : " + queryStringDecoder.parameters().get("yStep").get(0)); } } if (queryStringDecoder.parameters().get("yStepLeft") != null) { try { parameters.getImageParameters().setyStepLeft(Double.valueOf(queryStringDecoder.parameters().get("yStepLeft").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("yStepLeft format : " + queryStringDecoder.parameters().get("yStepLeft").get(0)); } } if (queryStringDecoder.parameters().get("yStepRight") != null) { try { parameters.getImageParameters().setyStepRight(Double.valueOf(queryStringDecoder.parameters().get("yStepRight").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("yStepRight format : " + queryStringDecoder.parameters().get("yStepRight").get(0)); } } if (queryStringDecoder.parameters().get("yUnitSystem") != null) { try { parameters.getImageParameters().setyUnitSystem(UnitSystem.valueOf(queryStringDecoder.parameters().get("yUnitSystem").get(0).toUpperCase())); } catch (IllegalArgumentException e) { throw new InvalidParameterValueException("Unknown yUnitSystem : " + queryStringDecoder.parameters().get("yUnitSystem").get(0).toUpperCase()); } } if (queryStringDecoder.parameters().get("connectedLimit") != null) { try { parameters.getImageParameters().setConnectedLimit(Integer.valueOf(queryStringDecoder.parameters().get("connectedLimit").get(0))); } catch (NumberFormatException e) { throw new InvalidParameterValueException("ConnectedLimit format : " + queryStringDecoder.parameters().get("connectedLimit").get(0)); } } return parameters; } private static long parseExtendedTime(String timeString, DateTimeZone tz) { Matcher matcher = EXTENDED_TIME_PATTERN.matcher(timeString); if (matcher.matches()) { String value = matcher.group(1); String unit = matcher.group(2); Long unitValue; // calc unit value if (unit.startsWith("s")) { unitValue = 1L; } else if (unit.startsWith("min")) { unitValue = 60L; } else if (unit.startsWith("h")) { unitValue = 3600L; } else if (unit.startsWith("d")) { unitValue = 86400L; } else if (unit.startsWith("w")) { unitValue = 604800L; } else if (unit.startsWith("mon")) { unitValue = 2678400L; } else if (unit.startsWith("y")) { unitValue = 31536000L; } else { unitValue = 60L; } // calc offset as (now) - (number * unit value) return (System.currentTimeMillis() / 1000L) - (Long.valueOf(value) * unitValue); } else if ("now".equals(timeString.toLowerCase())) { return System.currentTimeMillis() / 1000L; } else { return new DateTime(Long.valueOf(timeString) * 1000, tz).getMillis() / 1000L; } } }